package com.globallogic.qdumper.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.border.BevelBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

import com.globallogic.qdumper.FileService;
import com.globallogic.qdumper.QueryDumperService;
import com.globallogic.qdumper.bean.QueryItem;

public class MainForm extends JFrame
{
    private static final long serialVersionUID = 1L;

    private QueryDumperService qdumpService;
    private FileService fileService;

    private JTextArea sqlTextArea;
    private JTable queryItemTable;
    private JTextArea resultTextArea;

    private Properties properties = new Properties();
    private String sqlFolder;
    private String xmlFolder;

    private List<QueryItem> queryItems = new ArrayList<QueryItem>();


    public MainForm() throws Exception
    {
        super("Query dumper");

        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setSize(800, 600);
        setLayout(new BorderLayout());

        createGui();

        initData();

        setVisible(true);
    }

    private void initData() throws IOException
    {
        String propertyFile = System.getProperty("config.file", "config.properties");
        properties.load(getClass().getClassLoader().getResourceAsStream(propertyFile));

        qdumpService = new QueryDumperService();
        qdumpService.setDsnName(properties.getProperty("dsnName"));
        qdumpService.setUser(properties.getProperty("user"));
        qdumpService.setPassword(properties.getProperty("password"));
        sqlFolder = properties.getProperty("sqlFolder");
        xmlFolder = properties.getProperty("xmlFolder");
        fileService = new FileService();

        QueryItemTableModel queryItemTableModel = new QueryItemTableModel();
        queryItemTableModel.reload();

        queryItemTable.setModel(queryItemTableModel);
        ListSelectionListener queryItemTableSelectionListener = new ListSelectionListener()
                    {
            public void valueChanged(ListSelectionEvent e)
                        {
                QueryItem selectedItem = getSelectedQueryItem();
                if ( selectedItem != null )
                            {
                    sqlTextArea.setEnabled(true);
                    sqlTextArea.setText(selectedItem.getQueryText());
                    resultTextArea.setText(selectedItem.getResultText());
                }
                else
                {
                    sqlTextArea.setEnabled(false);
                    sqlTextArea.setText("Select a sql file to see its content.");
                    resultTextArea.setText("");
                }
            }
        };
        queryItemTable.getSelectionModel().addListSelectionListener(queryItemTableSelectionListener);
    }

    private QueryItem getSelectedQueryItem()
    {
        QueryItem selectedItem = null;
        if ( queryItemTable.getSelectedRow() != -1 )
        {
            selectedItem = queryItems.get(queryItemTable.getSelectedRow());
        }
        return selectedItem;
    }

    private void createGui()
    {
        JToolBar toolBar = new JToolBar();
        toolBar.add(new JButton(new ExecuteQueryAction()));

        sqlTextArea = new JTextArea(20, 200);
        sqlTextArea.setBorder(new BevelBorder(BevelBorder.LOWERED));
        sqlTextArea.setAutoscrolls(true);

        JPanel settingsPanel = new JPanel();
        settingsPanel.setLayout(new BoxLayout(settingsPanel, BoxLayout.Y_AXIS));

        JPanel sqlPanel = new JPanel(new BorderLayout());
        queryItemTable = new JTable();
        sqlPanel.add(new JScrollPane(queryItemTable), BorderLayout.WEST);
        sqlPanel.add(new JScrollPane(sqlTextArea), BorderLayout.CENTER);

        JPanel resultsPanel = new JPanel(new BorderLayout(2, 0));
        resultTextArea = new JTextArea();
        resultsPanel.add(new JScrollPane(resultTextArea), BorderLayout.CENTER);

        JPanel contentPanel = new JPanel(new GridLayout(2, 1));

        // add(settingsPanel, BorderLayout.CENTER);
        contentPanel.add(sqlPanel);
        contentPanel.add(resultsPanel);

        add(toolBar, BorderLayout.NORTH);
        add(contentPanel, BorderLayout.CENTER);
    }

    private JPanel createPanel(Component label, Component component)
    {
        JPanel panel = new JPanel(new GridLayout(1, 2));

        panel.add(label, BorderLayout.EAST);
        panel.add(component);

        return panel;
    }

    public static void main(String[] argc) throws Exception
    {
        new MainForm();
    }

    @SuppressWarnings("serial")
    private final class QueryItemTableModel extends DefaultTableModel
    {
        private static final int COLUMN_FNAME = 0;
        private static final int COLUMN_EXECTIME = 1;
        private static final int COLUMN_CHANGED = 2;

        void reload()
        {
            queryItems = fileService.getQueryItems(sqlFolder);
        }

        @Override
        public int getColumnCount()
        {
            return 3;
        }

        @Override
        public Class<?> getColumnClass(int column)
        {
            switch (column)
            {
            case COLUMN_FNAME:
                return String.class;
            case COLUMN_EXECTIME:
                return Long.class;
            case COLUMN_CHANGED:
                return Boolean.class;
            default:
                return super.getColumnClass(column);
            }
        }

        @Override
        public String getColumnName(int column)
        {
            switch (column)
            {
            case COLUMN_FNAME:
                return "Source query file";
            case COLUMN_EXECTIME:
                return "Executed time";
            case COLUMN_CHANGED:
                return "Changed";
            default:
                throw new IllegalStateException("Unsupported colmn No: " + column);
            }
        }

        @Override
        public int getRowCount()
        {
            return queryItems != null ? queryItems.size() : 0;
        }

        @Override
        public Object getValueAt(int row, int column)
        {
            QueryItem queryItem = queryItems.get(row);
            switch (column)
            {
            case COLUMN_FNAME:
                return queryItem.getQueryFileName();
            case COLUMN_EXECTIME:
                return queryItem.getExecutedTime();
            case COLUMN_CHANGED:
                return queryItem.isModifiedQuery();
            default:
                throw new IllegalStateException("Unsupported colmn No: " + column);
            }
        }

        @Override
        public void setValueAt(Object aValue, int row, int column)
        {
            // Read only table
        }
    }

    @SuppressWarnings("serial")
    private final class ExecuteQueryAction extends AbstractAction
    {
        private ExecuteQueryAction()
        {
            super("Execute all queries");
        }

        public void actionPerformed(ActionEvent e)
        {
            Cursor cursor = getCursor();
            try
            {
                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

                qdumpService.startSqlExecution(queryItems);
                fileService.flushResults(queryItems, xmlFolder);
            }
            catch ( Exception e1 )
            {
                e1.printStackTrace();
                JOptionPane.showConfirmDialog(MainForm.this, "Exception raized on sql execution: "
                    + e1.getMessage());
            }
            finally
            {
                setCursor(cursor);
            }
        }
    }
}
